var util = require("util");
var engine = require("../engine/gameEngine");
var sockets = require("../sockets");

exports.setModels = function(m) {
  models = m;
};

exports.setIo = function(i) {
  io = i;
};

exports.createGame = function(req, res) {
  models.Game.create({creatorPlayerId: req.user.id}, function(err, game) {
    models.GamePlayer.create({gameId: game.id, playerId: req.user.id}, function(err, gamePlayer) {
      game.displayFormat(function(err, gameD) {
        engine.handlePlay(req.user.id, gamePlayer, 'init', [], models, function(err, meta){
          engine.handlePlay(req.user.id, gamePlayer, 'join', [], models, function(err, unused){
            res.send(200);
          });
        });
      });
    });
  });
};

exports.playGame = function(req, res) {
  var gameId = req.query.gameId;
  var playerId = req.user.id;
  models.Game.findOne({where: {pk: gameId}}, function(err, game) {
    if(!game) {
      res.send(500, util.format("Game: %s does not exist", gameId));
    } else {
      models.GamePlayer.findOne({where: {
        gameId: game.id, playerId: playerId}}, function(err, gamePlayer) {
          if(!gamePlayer) {
            res.send(500, util.format("Not a member of this game", gameId));
          } else {
            gamePlayer.displayFormat(function(err, displayGamePlayer) {
              req.user.displayFormat(function(err, player) {
                game.displayFormat(function(err, game){
                  res.render('game/game.html', {
                    game: game,
                    gamePlayer: displayGamePlayer,
                    player: player,
                    joiner: req.flash('joiner'),
                    csrfToken: req.session._csrf});
                });
              });
            });
          }
        });
    }
  });
};

exports.joinGame = function(req, res) {
  var playerId = req.user.id;
  var gamePk = req.query.gameId;
  getGamePlayerByPlayerIdGamePk(playerId, gamePk, res, function(err, gamePlayer, game) {
    if(gamePlayer) {
      res.redirect(util.format('/playGame?gameId=%s', gamePk));
    } else {
      models.GamePlayer.create({
        gameId: game.id,
        playerId: playerId}, function(err, gamePlayer) {
          req.flash('joiner', true);
          engine.handlePlay(req.user.id, gamePlayer, 'join', [], models, function(err, unused){
            gamePlayer.displayFormat(function(err, gamePlayer){
              sockets.broadcastMessage(io, 'room change', game.pk, {
                present: true,
                gamePlayer: gamePlayer
              });
              res.redirect(util.format('/playGame?gameId=%s', gamePk));
            });
          });
        });
    }
  });
};

exports.sendChatMessage = function(req, res) {
  var playerId = req.user.id;
  var gamePk = req.body.gamePk;
  var gamePlayerPk = req.body.gamePlayerPk;
  models.findEntityByPk(gamePlayerPk, models.GamePlayer, function(err, gamePlayer) {
    if(gamePlayer.player() != playerId) {
      res.send(500, util.format("Not allowed to send chats for: %s", gamePlayerPk));
    }
    if(!gamePlayer) {
      res.send(500, util.format("Not a member of this game", gameId));
    } else {
      sockets.broadcastMessage(io, 'chat message', gamePk, {
        text: req.body.message,
        sender: req.body.name,
        time: new Date().getTime(),
        senderPk: gamePlayer.pk,
        remoteAvatar: req.body.remoteAvatar
      });
      res.send(200);
    }
  });
};

exports.sendPlay = function(req, res) {
  var playerId = req.user.id;
  var gamePk = req.body.gamePk;
  var gamePlayerPk = req.body.gamePlayerPk;
  models.findEntityByPk(gamePlayerPk, models.GamePlayer, function(err, gamePlayer) {
    if(gamePlayer.player() != playerId) {
      res.send(500, util.format("Not allowed to send plays for: %s", gamePlayerPk));
    }
    if(!gamePlayer) {
      res.send(500, util.format("Not a member of this game", gameId));
    } else {
      engine.handlePlay(req.user.id, gamePlayer, req.body.type, req.body.metadata, models, function(err, details){
        if (err) {
          res.send(500, err);
        } else{
          sockets.broadcastMessage(io, req.body.type, gamePk, {
            details: details,
            sender: req.body.name,
            type: req.body.type,
            time: new Date().getTime(),
            senderPk: gamePlayer.pk,
            remoteAvatar: req.body.remoteAvatar
          });
          res.send(200);
        }
      });
    }
  });
};

exports.getCards = function(req, res) {  
  var playerId = req.user.id;
  var gamePlayerPk = req.body.gamePlayerPk;
  var gamePk = req.body.gamePk;
  
  models.findEntityByPk(gamePk, models.Game, function(err, game) {
    game.getGamePlayerMetadata(["hands"], function(err, gamePlayerMetadata) {
      models.findEntityByPk(gamePlayerPk, models.GamePlayer, function(err, gamePlayer) {
        if(gamePlayer.player() != playerId) {
          res.send(500, util.format("Not allowed to send plays for: %s", gamePlayerPk));
        }
        if(!gamePlayer) {
          res.send(500, util.format("Not a member of this game", gameId));
        } else {
          var hands = gamePlayerMetadata.hands;
          var gamePlayerHands = [];
          for (handGamePlayerPk in hands) {
            var gamePlayerHand = hands[handGamePlayerPk].value[util.format("%s", game.session)];
            if (gamePlayer.pk != handGamePlayerPk) {
              var cc = 0;
              for (card in gamePlayerHand) {
                if (gamePlayerHand[card].modifier != "show-dry") {
                  gamePlayerHand[util.format("%s", ++cc)] = gamePlayerHand[card];
                  delete gamePlayerHand[card];
                }
              }
            }
            gamePlayerHands.push({gamePlayer: handGamePlayerPk, hand: gamePlayerHand});
          }
          res.send(gamePlayerHands);
        }
      });
    }, /* retrieveDbObject */ true);
  });
};

function getGamePlayerByPlayerIdGamePk(playerId, gamePk, res, callback) {
  models.Game.findOne({where: {pk: gamePk}}, function(err, game) {
    if(!game) {
      res.send(util.format("Game: %s does not exist", gamePk));
    } else {
      models.GamePlayer.findOne({where: {
        gameId: game.id, playerId: playerId}}, function(err, gamePlayer) {
          callback(err, gamePlayer, game);
      });
    }
  });
}
